﻿//
// Copyright (c) 2011 David Díaz & Fran Pedreira
//
// This file is part of PlanSim.
//
// PlanSim is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PlanSim is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PlanSim. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace PlanSim.Core
{
    public class ColaSJF : ICola
    {
		private class ComparadorDeDuracion : IComparer<IProceso>
		{
			public int Compare(IProceso x, IProceso y)
			{
				if (x.Duracion > y.Duracion)
					return 1;
				if (x.Duracion < y.Duracion)
					return -1;
				else
					return 0;
			}
		}

		/// <summary>
		/// Identificador de la cola.
		/// </summary>
		public string Nombre
		{
			get { return nombre; }
			//set { nombre = value; }
		}
		private string nombre;

        /// <summary>
        /// Devuevle una referencia al alemento i-esimo.
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public IProceso Elemento(int i)
        {
            if (cola.Count >= i)
                return cola[i];
            else
                return null;
        }

		/// <summary>
		/// Prioridad de la cola.
		/// </summary>
		public int Prioridad
		{
			get { return prioridad; }
			//set { prioridad = value; }
		}
		private int prioridad;

		PriorityQueue<IProceso> cola;

		public ColaSJF(string nombre, int prioridad)
		{
			this.nombre = nombre;
			this.prioridad = prioridad;

			cola = new PriorityQueue<IProceso>(new ComparadorDeDuracion());
		}

        /// <summary>
        /// Añade un proceso a la cola.
        /// </summary>
        /// <param name="proceso"></param>
        public void Encolar(IProceso proceso)
        {
			cola.Push(proceso);
        }

        /// <summary>
        /// Extrae un proceso de la cola.
        /// </summary>
        /// <returns></returns>
        public IProceso Desencolar()
        {
			IProceso p = null;

			if (cola.Count>0)
				p = cola.Pop();

			return p;
        }

        /// <summary>
        /// Obtiene el número de procesos que contiene la cola.
        /// </summary>
        /// <returns></returns>
        public int Elementos()
        {
            return cola.Count;
        }

        /// <summary>
        /// Indica si la cola contiene el proceso especificado.
        /// </summary>
        /// <param name="proceso"></param>
        /// <returns></returns>
        public bool Contiene(IProceso proceso)
        {
            return cola.Contains(proceso);
        }

        /// <summary>
        /// Indica si, atendiendo a la estrategia de la cola, un proceso debe dejar libre la CPU.
        /// </summary>
        /// <param name="planificador"></param>
        /// <returns></returns>
		public bool DebeSalirProceso(IPlanificador planificador)
		{
			return false; // Apropiativo (no expropiable)
		}
    }
}
